﻿
//  凑数 找硬币  动态规划
//  利用hash存储能使用的硬币  
//  再利用状态转移方程  dp[i] 表示 到达当前面值的最少硬币
//  注意初始化dp表  以免填错
//  动态规划 --- 完全背包问题  
#include <iostream>
#include <vector>
using namespace std;
bool vis[100001];
int main()
{
    int n, target;
    cin >> n >> target;
    vector<int> nums(n), dp(target + 1, target*2);
    for (int i = 0; i < n; i++)
    {
        cin >> nums[i];
        vis[nums[i]] = true;
        if (nums[i] <= target)   //  初始化  已有的面值都置为 1 
            dp[nums[i]] = 1;
    }
    if (target == 0)   //  注意边界情况  
    {
        cout << 0;
        return 0;
    }
    for (int i = 1; i <= target; i++)
    {
        for (int j = 0; j < i; j++)
        {
            if (dp[j] != 0 && vis[i - j])
            {
                dp[i] = min(dp[i], dp[j] + 1);
            }
        }
    }
    if (dp[target] == target * 2)   //  能否到达最后的面值 
        cout << -1;
    else
        cout << dp[target];
    return 0;
}


//  找出符合种类数量的子串   l - r 区间
//  滑动窗口+前缀和  
//  
#include <iostream>
#include <string>
using namespace std;
int n, l, r;
string s;
// 找出字符种类在 [1, x] 之间的⼦串的个数
long long find(int x)
{
    if (x == 0) return 0;
    // 滑动窗⼝
    int left = 0, right = 0;
    int hash[26] = { 0 }, kinds = 0; // 统计窗⼝内字符种类的个数
    long long ret = 0;

    while (right < n)
    {
        if (hash[s[right] - 'a']++ == 0) kinds++;
        while (kinds > x)
        {
            if (hash[s[left] - 'a']-- == 1) kinds--;
            left++;
        }
        ret += right - left + 1;  //  表示从left开始  符合 1 - x 种类的子串数量  前缀和思想  
        right++;
    }

    return ret;
}
int main()
{
    cin >> n >> l >> r >> s;

    cout << find(r) - find(l - 1) << endl;  //  1-l  1-r  的子串数量 相减就是   l-r区间的子串数量
                                                //  利用前缀和 处理区间的问题  
    return 0;

